package com.wxl.multi.redis;

import io.lettuce.core.ReadFrom;
import io.lettuce.core.TimeoutOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.Arrays;

@Configuration
@SuppressWarnings("Duplicates")
public class Cluster2RedisConfig {

    @Value("${spring.redis.cluster2.nodes}")
    private String cluster2Nodes;

    @Value("${spring.redis.cluster2.password}")
    private String cluster2Password;

    @Value("${spring.redis.cluster2.lettuce.pool.max-active}")
    private int cluster2MaxActive;

    @Value("${spring.redis.cluster2.lettuce.pool.max-idle}")
    private int cluster2MaxIdle;

    @Value("${spring.redis.cluster2.lettuce.pool.min-idle}")
    private int cluster2MinIdle;

    @Value("${spring.redis.cluster2.lettuce.pool.max-wait}")
    private Duration cluster2MaxWait;

    @Value("${spring.redis.cluster2.lettuce.topology-refresh.enabled}")
    private boolean cluster2TopologyRefreshEnabled;

    @Value("${spring.redis.cluster2.lettuce.topology-refresh.adaptive}")
    private boolean cluster2TopologyRefreshAdaptive;

    @Value("${spring.redis.cluster2.lettuce.topology-refresh.period}")
    private Duration cluster2TopologyRefreshPeriod;

    @Value("${spring.redis.cluster2.lettuce.topology-refresh.timeout}")
    private Duration cluster2TopologyRefreshTimeout;

//    // 创建共享的 ClientResources
//    @Bean(destroyMethod = "shutdown")
//    public ClientResources clientResources() {
//        return DefaultClientResources.builder().build();
//    }

    // 配置第二个Redis集群的连接工厂
    @Bean(name = "cluster2RedisConnectionFactory")
    public LettuceConnectionFactory cluster2RedisConnectionFactory(ClientResources clientResources) {
        RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(Arrays.asList(cluster2Nodes.split(",")));
        if (cluster2Password != null && !cluster2Password.isEmpty()) {
            clusterConfig.setPassword(cluster2Password);
        }

        GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxTotal(cluster2MaxActive);
        poolConfig.setMaxIdle(cluster2MaxIdle);
        poolConfig.setMinIdle(cluster2MinIdle);
        poolConfig.setMaxWaitMillis(cluster2MaxWait.toMillis());

        ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                .enableAllAdaptiveRefreshTriggers()
                .enablePeriodicRefresh(cluster2TopologyRefreshPeriod) // 每隔5秒拿一次集群的拓扑信息
                .refreshPeriod(cluster2TopologyRefreshPeriod)
                .build();

        ClusterClientOptions clientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(topologyRefreshOptions)
                //redis 命令超时时间 根据自己需要设置这里设置为2s
                .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(2)))
                .autoReconnect(true)
                .build();

        // 使用 LettucePoolingClientConfiguration 来配置连接池
        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofSeconds(5000000))
                .clientOptions(clientOptions)
                .poolConfig(poolConfig)
                .readFrom(ReadFrom.ANY)
                .clientResources(clientResources)
                .build();

        return new LettuceConnectionFactory(clusterConfig, clientConfig);
    }

    // 配置第二个Redis集群的模板
    @Bean(name = "cluster2RedisTemplate")
    public RedisTemplate<String, String> cluster2RedisTemplate(@Qualifier("cluster2RedisConnectionFactory") LettuceConnectionFactory connectionFactory) {
        final RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}
